﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;

namespace RegexTests
{
    class Program
    {
        private const int x = 40;
        private static string pattern;
        private static int countGroups { get; set; }
        private static int nullGroups { get; set; }
        private static int stringCount { get; set; }
        private static int matchCount { get; set; }
        static void Main( string[ ] args )
        {
            if ( args.Length == 0 )
            {
                Print( "\r\nPlease provide an Argument\r\n", ConsoleColor.Red );
                helpText( );
                return;
            }
            switch (args[ 0 ])
            {
                case "-h":
                    helpText( );
                    return;
                case "-f":
                    //Use file as Subject
                    foreach ( string item in args )
                    {
                        if ( item == null )
                        {
                            Print( "Check the Syntax of your arguments:", ConsoleColor.Red );
                            helpText( );
                            return;
                        }
                    }
                    pattern = args[ 2 ];
                    Print( "\nPattern: {0}", ConsoleColor.White, pattern );
                    processFile( args[ 1 ] );
                    break;
                case "-s":
                    //Use string as subject
                    foreach ( string item in args )
                    {
                        if ( item == null )
                        {
                            Print( "Check the Syntax of your arguments:", ConsoleColor.Red );
                            helpText( );
                            return;
                        }
                    }
                    pattern = args[ 2 ];
                    Print( "\nPattern: {0}", ConsoleColor.White, pattern );
                    processString( args[ 1 ] );
                    break;
                default:
                    Print( "Incorrect Syntax:", ConsoleColor.Red );
                    helpText( );
                    break;
            }
            if ( countGroups == nullGroups )
            {
                Print( string.Empty.PadLeft( x, '*' ), ConsoleColor.Green);
                Print( "  Zero Matches in Subject",ConsoleColor.Magenta );
                Print( string.Empty.PadLeft( x, '*' ),  ConsoleColor.Green);
            }
            Print( "Total Number of Strings = {0}\nTotal Number of Matches = {1}", ConsoleColor.Green, stringCount, matchCount );
            Console.WriteLine( );
        }

        private static void Print( string msg, ConsoleColor consoleColor, params object[ ] args )
        {
            ConsoleColor defaultForeColor = Console.ForegroundColor;
            Console.ForegroundColor = consoleColor;
            Console.Write( msg, args );
            Console.ForegroundColor = defaultForeColor;
        }

        private static void helpText( )
        {
            Print( "\r\nDeveloped by:\r\n Stephen Smith, VipX1 Development\r\n", ConsoleColor.Gray );
            Print( "\r\nSyntax:\r\n RegexTests  [ -s \"subject\" || -f \"FileName\" ] [ \"pattern\" ]\r\n", ConsoleColor.Cyan );
        }

        private static void processFile( string fileName )
        {
            List<string> strings = new List<string>();
            //Confirm file exists
            if ( !( new FileInfo(fileName) ).Exists )
            {
                Print( "File [{0}] not found!", ConsoleColor.Red, fileName );
                return;
            }
            try
            {
                using ( var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read) )
                using ( var sr = new StreamReader(fileStream) )
                {
                    while ( sr.Peek( ) > -1 )
                    {strings.Add( sr.ReadLine( ) );}
                    foreach ( string str in strings )
                    {processString( str );}
                }
            }
            catch (Exception ex)
            {
                Print( "Exception:\n{0}", ConsoleColor.Red, ex.Message );
                return;
            }
        }

        private static void processString( string str )
        {
            stringCount++;
            try
            {
                //Set the pattern
                Regex regex = new Regex(pattern);
                var match = regex.Match( str );
                var groupNames = regex.GetGroupNames( );
                foreach ( Group group in match.Groups )
                {
                    countGroups++;
                    if ( !match.Success )
                    {
                        nullGroups++;
                    }
                }
                while ( match.Success )
                {
                    matchCount++;
                    Print( "\r\nText: (String No. {0})\r\n", ConsoleColor.Green, stringCount );
                    Print( "{0}\r\n", ConsoleColor.White, str );
                    int i = 0;
                    Print( "{0}\r\n", ConsoleColor.Green, string.Empty.PadLeft( x, '*' ) );
                    Print( "({0}) Match = {1} @{2}:{3}\r\n", ConsoleColor.Magenta, matchCount, match.Success, match.Index, match.Length + match.Index );
                    Print( "({0}) {1}:\r\n", ConsoleColor.Cyan, match.Groups.Count, ( ( match.Groups.Count ) == 1 ) ? "Group" : "Groups" );
                    foreach ( Group group in match.Groups )
                    {
                        if ( group.Value != null )
                        {
                            Print( "{0}\r\n", ConsoleColor.Green,string.Empty.PadLeft( x, '-' ) );
                            Print( "({0}) Group Value:\r\n", ConsoleColor.Cyan, groupNames[ i++ ] );
                            if ( i > 1 )
                            {
                                Print( "{0}\r\n", ConsoleColor.Yellow, group.Value );
                            }
                            else
                            {
                                Print( "{0}\r\n", ConsoleColor.Cyan, group.Value );
                            }
                            if ( group.Captures.Count > 0 )
                            {
                                int j = 0;
                                foreach ( var capture in group.Captures )
                                {
                                    Print( "({0}) Capture:\r\n", ConsoleColor.White, j++ );
                                    Print( "{0}\r\n", ConsoleColor.Cyan, capture );
                                }
                            }
                        }
                    }
                    Print( "{0}\r\n", ConsoleColor.Green,string.Empty.PadLeft( x, '*' ) );
                    match = match.NextMatch( );
                }
            }
            catch (Exception ex)
            {
                Print( "Exception:\n{0}", ConsoleColor.Red, ex.Message );
                return;
            }
        }
    }
}
